﻿//
//  application.cpp
//
//  Created by harrse on 4/24/17.
//  Copyright © 2017 harrse. All rights reserved.
//

#include "modules/server.hpp"
#include "modules/client.hpp"
#include "modules/middlewares/session.hpp"
#include "business/dao/User.hpp"
#include "business/service/setup.hpp"
#include "business/service/session.hpp"
#include "business/service/user.hpp"

using namespace diylane::http;

namespace diylane
{
struct Application
{
    Logger logger;
    postgres::Pool dbPool;
    client::Pool clientPool;
    HttpServer server;
    HttpSessionMiddleware sessionMiddleware;

    struct {
        dao::User user;
    } DAO;

    struct {
        service::Setup setup;
        service::Session session;
        service::User user;
    } SERVICE;

    Application()
    {
        // mem trap
        char* trapA = (char*)malloc(32);
        strcpy(trapA, "trapA");
        
        // curl
        curl_global_init(CURL_GLOBAL_DEFAULT);

        // logger
        Logger::singleton(&logger);

        // client pool
        client::Pool::singleton(&clientPool);

        // middlewares
        server.addMiddleware(&sessionMiddleware);

        // dao
        dao::User::singleton(&DAO.user).initialize(&dbPool);
        
        // service
        service::Setup::singleton(&SERVICE.setup).initialize(&dbPool);
        service::Session::singleton(&SERVICE.session).initialize(&dbPool);
        service::User::singleton(&SERVICE.user).initialize(&dbPool);
    }

    virtual ~Application()
    {
        curl_global_cleanup();
    }

    // set up builtin configurations
    virtual bool setup()
    {
        // initialize database pool
        dbPool.max_workers = 100;
        dbPool.config->host = "crazbot.com";
        dbPool.config->dbname = "diylane_test";
        dbPool.config->user = "testa";
        dbPool.config->password = "zxcv123";

        // installing session middleware
        sessionMiddleware.pool.max_workers = 5;
        sessionMiddleware.pool.addServer("crazbot.com", "is9933laxcj3kknmd3dShs0fa");
        return true;
    }

    int run(int argc, const char *argv[])
    {
        server.route("/client", [](HttpRequest *request, HttpResponse *response) {
            std::string clientError = "";
            client::AcquiredWorker client(&client::Pool::singleton(), clientError);
            Request req;
            Response resp;
            req.url = "http://www.baidu.com";
            const char *url = request->getParameter("url");
            if (url)
            {
                req.url = url;
            }
            response->content += "target url is ";
            response->content += req.url;
            response->content += "\r\n";
            req.cookieJar.set(new Cookie("abc", "zzzzz"));
            req.cookieJar.set(new Cookie("PTOKEN", "A428DB28EAE41DF7BE9F34329B2D5238"));
            if (!client.unwrap()->doRequest(&req, resp))
            {
                response->content += "error: ";
                response->content += resp.error;
            }
            response->content += "test ok.\r\n";
        });

        server.route("/postgres", [](HttpRequest *request, HttpResponse *response) {
            service::Arguments args;
            service::Result result;
            args.set("username", request->getParameter("username"));
            args.set("password", request->getParameter("password"));
            service::Setup::singleton().createAdmin(args, result);
            response->content += result.dump();
        });

        server.route("/sleep", [](HttpRequest *request, HttpResponse *response) {
            boost::this_thread::sleep(boost::posix_time::milliseconds(5000));
            response->content += "Sample content.\r\n";
        });

        server.route("/json", [](HttpRequest *request, HttpResponse *response) {
            HttpSession *session = (HttpSession *)request->getContext(Middleware_Session);
            if (session->empty())
            {
                session->createNew();
                rapidjson::SetValueByPointer(session->data, "/abc", 1234555);
                rapidjson::SetValueByPointer(session->data, "/efg", "sss");
            }
            response->content_type = "application/json";
            response->content += "{\"abc\":123,\"content\":null}";
        });

        server.route("/shutdown", [](HttpRequest *request, HttpResponse *response) {
            request->__server->shutdown = true;
        });

        return server.port(18081).run();
    }
};
}
